﻿using System;
using System.Runtime.InteropServices;

namespace CSharpHelpers.Medias
{
    /// <summary>
    /// 显示器屏幕设置
    /// add by john 2016-08-04
    /// </summary>
    public class DisplaySettingHelper
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct DEVMODE
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dmDeviceName;

            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;
            public int dmPositionX;
            public int dmPositionY;
            public int dmDisplayOrientation;
            public int dmDisplayFixedOutput;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dmFormName;

            public short dmLogPixels;
            public short dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
            public int dmICMMethod;
            public int dmICMIntent;
            public int dmMediaType;
            public int dmDitherType;
            public int dmReserved1;
            public int dmReserved2;
            public int dmPanningWidth;
            public int dmPanningHeight;
        };

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int ChangeDisplaySettings([In]ref DEVMODE lpDevMode, int dwFlags);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int EnumDisplaySettings(string lpszDeviceName, Int32 iModeNum, ref DEVMODE lpDevMode);

        // constants
        public const int DISP_CHANGE_SUCCESSFUL = 0;
        public const int ENUM_CURRENT_SETTINGS = -1;
        public const int DMDO_DEFAULT = 0;
        public const int DMDO_90 = 1;
        public const int DMDO_180 = 2;
        public const int DMDO_270 = 3;

        /// <summary>
        /// 修改屏幕分辨率
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public static void ChangeResolution(int width, int height)
        {
            DEVMODE dm = new DEVMODE();
            dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
            int mybool = EnumDisplaySettings(null, 0, ref  dm);
            dm.dmPelsHeight = height;
            dm.dmPelsWidth = width;
            dm.dmDisplayFrequency = 60;
            dm.dmBitsPerPel = 32;

            int iRet = ChangeDisplaySettings(ref  dm, 0);
            if (DISP_CHANGE_SUCCESSFUL != iRet)
            {
                // add exception handling here
            }
        }

        /// <summary>
        /// 屏幕旋转90度
        /// </summary>
        public static void ChangingScreenOrientation90()
        {
            // initialize the DEVMODE structure
            DEVMODE dm = new DEVMODE();
            dm.dmDeviceName = new String(new char[32]);
            dm.dmFormName = new String(new char[32]);
            dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
            dm.dmDriverExtra = 0;
            dm.dmDisplayFrequency = 60;

            if (0 != EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
            {
                // swap width and height
                int temp = dm.dmPelsHeight;
                dm.dmPelsHeight = dm.dmPelsWidth;
                dm.dmPelsWidth = temp;

                // determine new orientation
                switch (dm.dmDisplayOrientation)
                {
                    case DMDO_DEFAULT:
                        dm.dmDisplayOrientation = DMDO_270;
                        break;
                    case DMDO_270:
                        dm.dmDisplayOrientation = DMDO_180;
                        break;
                    case DMDO_180:
                        dm.dmDisplayOrientation = DMDO_90;
                        break;
                    case DMDO_90:
                        dm.dmDisplayOrientation = DMDO_DEFAULT;
                        break;
                    default:
                        break;
                }

                int iRet = ChangeDisplaySettings(ref dm, 0);
                if (DISP_CHANGE_SUCCESSFUL != iRet)
                {
                    // add exception handling here
                }

            }
        }

        /// <summary>
        /// 屏幕旋转180度
        /// </summary>
        public static void ChangingScreenOrientation180()
        {
            // initialize the DEVMODE structure
            DEVMODE dm = new DEVMODE();
            dm.dmDeviceName = new String(new char[32]);
            dm.dmFormName = new String(new char[32]);
            dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
            dm.dmDriverExtra = 0;
            dm.dmDisplayFrequency = 60;

            if (0 != EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
            {
                // determine new orientation
                switch (dm.dmDisplayOrientation)
                {
                    case DMDO_DEFAULT:
                        dm.dmDisplayOrientation = DMDO_180;
                        break;
                    case DMDO_270:
                        dm.dmDisplayOrientation = DMDO_90;
                        break;
                    case DMDO_180:
                        dm.dmDisplayOrientation = DMDO_DEFAULT;
                        break;
                    case DMDO_90:
                        dm.dmDisplayOrientation = DMDO_270;
                        break;
                    default:
                        break;
                }

                int iRet = ChangeDisplaySettings(ref dm, 0);
                if (DISP_CHANGE_SUCCESSFUL != iRet)
                {
                    // add exception handling here
                }
            }

        }
    }
}
